/**
 * Project: yui3-common-utils
 * Class TreeNodeUtils
 * Version 1.0
 * File Created at 2019年3月29日
 * $Id$
 * author yuyi
 * email 1060771195@qq.com
 */
package yui.comn.mybatisx.extension.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.util.CollectionUtils;

import yui.comn.mybatisx.core.toolkit.EntityUtils;
import yui.comn.mybatisx.extension.node.TreeNode;

/**
 * <p>
 * 树形结构生成工具
 * </p>
 *
 * @author yuyi (1060771195@qq.com)
 */
public class TreeNodeUtils {

    /**
     * 树形结构生成处理, vo对象将有Dto通过名称规范生成
     */
    public static <T extends TreeNode<T>, D> List<T> dtoListHandle(List<D> dtoList, Class<T> nodeClass) {
        return dtoListHandle(dtoList, nodeClass, null);
    }
    
    /**
     * 树形结构生成处理, vo对象将有Dto通过名称规范生成
     */
	public static <T extends TreeNode<T>, D> List<T> dtoListHandle(List<D> dtoList, Class<T> nodeClass, Long pid) {
    	if (CollectionUtils.isEmpty(dtoList)) {
    		return Collections.emptyList();
    	}
    	
    	List<T> nodeList = new ArrayList<>();
    	for (D dto : dtoList) {
    		T node = ConvertUtils.convert(EntityUtils.getVo(dto), nodeClass);
    		nodeList.add(node);
    	}
    	return treeNodeHandle(nodeList, pid);
    }
    
    /**
     * 树形结构生成处理
     */
    public static <T extends TreeNode<T>, V> List<T> voListHandle(List<V> voList, Class<T> nodeClass) {
    	return voListHandle(voList, nodeClass, null);
    }
    
    /**
     * 树形结构生成处理
     */
    public static <T extends TreeNode<T>, V> List<T> voListHandle(List<V> voList, Class<T> nodeClass, Long pid) {
    	if (CollectionUtils.isEmpty(voList)) {
    		return Collections.emptyList();
    	}
    	
    	List<T> nodeList = new ArrayList<>();
    	for (V vo : voList) {
    		T node = ConvertUtils.convert(vo, nodeClass);
    		nodeList.add(node);
    	}
    	return treeNodeHandle(nodeList, pid);
    }
    
    /**
     * 树形结构生成处理
     */
    public static <T extends TreeNode<T>> List<T> treeNodeHandle(List<T> nodeList) {
        return treeNodeHandle(nodeList, null);
    }
    
    /**
     * 树形结构生成处理
     */
    public static <T extends TreeNode<T>> List<T> treeNodeHandle(List<T> nodeList, Long pid) {
        if (CollectionUtils.isEmpty(nodeList)) {
            return Collections.emptyList();
        }
        
        seqHandle(nodeList);
        childFindParentHandler(nodeList);
        
        List<T> resultList = new ArrayList<>();
        if (null == pid) {
            keepTrunk(resultList, nodeList, 1);
        } else {
            keepTrunk(resultList, nodeList, 1, pid);
        }
        return resultList;
    }
    
    /**
     * 保留树形结构主干
     */
    private static <T extends TreeNode<T>> List<T> keepTrunk(List<T> resultList, 
            List<T> nodeList, int level, long pid) {
        for (T node : nodeList) {
            if (null != node.getPid() && (pid == node.getPid().longValue() || level > 1)) {
                if (pid == node.getPid().longValue()) {
                    resultList.add(node);
                }
                node.setLevel(level);
                
                if (!CollectionUtils.isEmpty(node.getChildren())) {
                    keepTrunk(resultList, node.getChildren(), level + 1, pid);
                }
            }
        }
        return resultList;
    }
    
    /**
     * 保留树形结构主干
     */
    private static <T extends TreeNode<T>> List<T> keepTrunk(List<T> resultList, 
            List<T> nodeList, int level) {
        for (T node : nodeList) {
            if (null == node.getPid() || level > 1) {
                if (null == node.getPid()) {
                    resultList.add(node);
                }
                node.setLevel(level);
                
                if (!CollectionUtils.isEmpty(node.getChildren())) {
                    keepTrunk(resultList, node.getChildren(), level + 1);
                }
            }
        }
        return resultList;
    }
    
    /**
     * 子项关联到父项，就关联到父项下面
     */
    private static <T extends TreeNode<T>> void childFindParentHandler(List<T> nodeList) {
        for (T node : nodeList) {
            if (null != node.getPid()) {
                T pNode = getTreeNode(nodeList, node.getPid());
                if (null != pNode) {
                    pNode.addChild(node);
                }
            }
        }
    }
    
    /**
     * 获取项
     */
    private static <T extends TreeNode<T>> T getTreeNode(List<T> nodeList, long id) {
        for (T node : nodeList) {
            if (id == node.getId().longValue()) {
                return node;
            }
        }
        return null;
    }
    
    /**
     * 排序
     */
    private static <T extends TreeNode<T>> List<T> seqHandle(List<T> nodeList) {
        Collections.sort(nodeList, new Comparator<T>() {
            @Override
            public int compare(T o1, T o2) {
                if (o1.getSeq() > o2.getSeq()) {
                    return 1;
                } else if (o1.getSeq() == o2.getSeq()) {
                    return 0;
                }
                return -1;
            }
        });
        return nodeList;
    }
}
